#include "QImageProcessScene.h"
#include <QRgb>
#include <math.h>

//_________________________________________________________________________
QImageProcessScene::QImageProcessScene(int frameHeight,
                                       int frameWidth,
                                       CHardwareParams* hwParams)
{
    m_FrameHeight = frameHeight;
    m_FrameWidth = frameWidth;
    m_HWParams = hwParams;

    if (strncmp(m_HWParams->m_Product, MOUSSAVI_PRODUCT_ID,
                strlen(MOUSSAVI_PRODUCT_ID)) == 0)
    {
        m_SceneType = SCENE_MOUSSAVI;
        m_BackgroundImage.load(MOUSSAVI_BACK_IMAGE_RESOURCE);

    }
    else if (strncmp(m_HWParams->m_Product, ANIBIKE_PRODUCT_ID,
                     strlen(ANIBIKE_PRODUCT_ID)) == 0)
    {
        m_SceneType = SCENE_ANIBIKE;
        m_BackgroundImage.load(ANIBIKE_BACK_IMAGE_RESOURCE);
        m_ForegroundImage.load(ANIBIKE_FRONT_IMAGE_RESOURCE);
    }
    else        // Unrecognized product
    {
        m_SceneType = SCENE_UNKNOWN;
    }

    m_HWDataSize = m_HWParams->FlashBlockSizeBytes*m_HWParams->NumOfBlocksForFrame;
    m_HWData = new unsigned char[m_HWDataSize*2];

    m_DrawingBack = false;
    m_DrawingFore = false;
}

//_________________________________________________________________________
QImageProcessScene::~QImageProcessScene()
{
    delete []m_HWData;
}

//_________________________________________________________________________
void QImageProcessScene::setHardwareParams (CHardwareParams* hwParams)
{
    if (hwParams!=NULL)
        m_HWParams = hwParams;
}

//_________________________________________________________________________
void QImageProcessScene::convertPolarPicture(QImage& image, double invisibleRadRatio)
{
    if (image.isNull ())
        return ;

    // duplicate the incoming image
    int origHeight = image.height();
    int origWidth = image.width();

    int left, right, top, bottom;
    if (origHeight > origWidth)
    {
        left = 0;
        right = origWidth;
        top = origHeight/2-origWidth/2;
        bottom = origHeight/2+origWidth/2;
    }
    else
    {
        top = 0;
        bottom = origHeight;
        left = origWidth/2-origHeight/2;
        right = origWidth/2+origHeight/2;
    }

    QImage sqImage = image.copy(left, top, right-left, bottom-top);
    int sqHeight = sqImage.height();
    int sqWidth = sqImage.width();

    int sqCenterX = sqWidth/2;
    int sqCenterY = sqHeight/2;

    double radOut = sqCenterX;
    double radIn = invisibleRadRatio*radOut;
    double dRad = (radOut - radIn)/m_HWParams->NumberOfLEDs;
    double dPhi = 360.0 / (double)(ANIBIKE_NUMOFRADS);
    double phiStart = 0.0;      // fisrt map 0->360
    double curRad, curPhi;
    int radY, phiX;

    // the first radius will be the middle of the first interval
    double radStart = radIn + dRad/2.0;
    int filterFactor = (int)(dRad/3);       // this filter will average over a square

    QImage polarImage(ANIBIKE_NUMOFRADS, m_HWParams->NumberOfLEDs, QImage::Format_RGB888);

    for (radY=0, curRad = radStart; radY < m_HWParams->NumberOfLEDs; radY ++, curRad+=dRad )
    {
        for (phiX = 0, curPhi = phiStart; phiX < ANIBIKE_NUMOFRADS; phiX ++, curPhi+=dPhi)
        {
            double curX, curY;

            if (curPhi >= 0.0 && curPhi < 90.0)                 // first qt
            {
                curX = curRad*cos(curPhi/180.0*ANIBIKE_PI);
                curY = curRad*sin(curPhi/180.0*ANIBIKE_PI);
            }
            else if (curPhi >= 90.0 && curPhi < 180.0)          // second qt
            {
                curX = -curRad*cos((180-curPhi)/180.0*ANIBIKE_PI);
                curY = curRad*sin((180-curPhi)/180.0*ANIBIKE_PI);
            }
            else if (curPhi >= 180.0 && curPhi < 270.0)         // third qt
            {
                curX = -curRad*cos((curPhi-180)/180.0*ANIBIKE_PI);
                curY = -curRad*sin((curPhi-180)/180.0*ANIBIKE_PI);
            }
            else                                                // fourth qt
            {
                curX = curRad*cos((360-curPhi)/180.0*ANIBIKE_PI);
                curY = -curRad*sin((360-curPhi)/180.0*ANIBIKE_PI);
            }


            int coordX = (int)(curX+sqCenterX), coordY = (int)(curY+sqCenterY);
            int avLeft = (coordX-filterFactor>=0)?coordX-filterFactor:0;
            int avRight = (coordX+filterFactor<sqWidth)?coordX+filterFactor:sqWidth;
            int avTop = (coordY-filterFactor>=0)?coordY-filterFactor:0;
            int avBottom = (coordY+filterFactor<sqHeight)?coordY+filterFactor:sqHeight;

            // average the current avSquare
            double sumSqRed = 0.0;
            double sumSqGreen = 0.0;
            double sumSqBlue = 0.0;
            double areaSq = abs((avRight-avLeft)*(avBottom-avTop));

            for (int k=avLeft; k<avRight; k++)
            {
                for (int t=avTop; t<avBottom; t++)
                {
                    QRgb col = sqImage.pixel(k,t);
                    sumSqRed+=qRed(col);
                    sumSqGreen+=qGreen(col);
                    sumSqBlue+=qBlue(col);
                }
            }

            QRgb newCol = qRgb(sumSqRed/areaSq, sumSqGreen/areaSq, sumSqBlue/areaSq);

            polarImage.setPixel(phiX, radY, newCol);
        }
    }

    polarImage.save("c://anibike.bmp");
    image = polarImage;
}

//_________________________________________________________________________
void QImageProcessScene::convertColorDepth(QImage& image)
{
    if (image.isNull ())
        return;

    int i,j;
    int h = image.height ();
    int w = image.width ();
    int maxValueR=0x00,maxValueG=0x00,maxValueB=0x00;
    int minValueR=0xFF,minValueG=0xFF,minValueB=0xFF;
    double maxValueGlob,minValueGlob;

    double numOfLevels = pow(2.0, m_HWParams->ColorDepth);
    double stepSize = 256.0/numOfLevels;

    // First we want to fix the picture dynamic range
    for (i = 0; i < w; i ++)
    {
        for (j = 0; j < h; j ++)
        {
            QRgb col = image.pixel(i,j);
            int R = qRed(col);
            int G = qGreen(col);
            int B = qBlue(col);

            if (maxValueR < R)  maxValueR = R;
            if (maxValueG < G)  maxValueG = G;
            if (maxValueB < B)  maxValueB = B;

            if (minValueR > R)  minValueR = R;
            if (minValueG > G)  minValueG = G;
            if (minValueB > B)  minValueB = B;
        }
    }

    // calculate the minmax and maxmin from the information
    if (maxValueR<=maxValueG && maxValueR<=maxValueB)
        maxValueGlob = maxValueR;
    else if (maxValueG<=maxValueR && maxValueG<=maxValueB)
        maxValueGlob = maxValueG;
    else if (maxValueB<=maxValueR && maxValueB<=maxValueG)
        maxValueGlob = maxValueB;

    if (minValueR>=minValueG && minValueR>=minValueB)
        minValueGlob = minValueR;
    else if (minValueG>=minValueR && minValueG>=minValueB)
        minValueGlob = minValueG;
    else if (minValueB>=minValueR && minValueB>=minValueG)
        minValueGlob = minValueB;

    // Grow the contrast according to the statistics on the picture and convert to Nbit values
    for (i = 0; i < w; i ++)
    {
        for (j = 0; j < h; j ++)
        {
            QRgb col = image.pixel(i,j);
            //double dR = (((double)(qRed(col))-minValueGlob)*255.0/(maxValueGlob-minValueGlob))/stepSize;
            //double dG = (((double)(qGreen(col))-minValueGlob)*255.0/(maxValueGlob-minValueGlob))/stepSize;
            //double dB = (((double)(qBlue(col))-minValueGlob)*255.0/(maxValueGlob-minValueGlob))/stepSize;

            double dR = ((double)(qRed(col)))/stepSize;
            double dG = ((double)(qGreen(col)))/stepSize;
            double dB = ((double)(qBlue(col)))/stepSize;

            int r,g,b;
            int maxVal = (int)(numOfLevels)-1;

            if (dR>maxVal)      r = maxVal;
            else if (dR<0.0)    r = 0;
            else                r = (int)dR;
            if (dG>maxVal)      g = maxVal;
            else if (dG<0.0)    g = 0;
            else                g = (int)dG;
            if (dB>maxVal)      b = maxVal;
            else if (dB<0.0)    b = 0;
            else                b = (int)dB;

            col = qRgb(r, g, b);
            image.setPixel (i, j, col);
        }
    }
}

//_________________________________________________________________________
void QImageProcessScene::convertToHardwareFrame(void)
{
    if (m_SceneType == SCENE_MOUSSAVI)
        convertToMoussaviFrame();
    else if (m_SceneType == SCENE_ANIBIKE)
        convertToAniBikeFrame();
}

//_________________________________________________________________________
void QImageProcessScene::convertToMoussaviFrame(void)
{
    memset(m_HWData, 0, m_HWDataSize);

    if (m_ConvertedImage.isNull ())
    {
        // Problem here!!
        return ;
    }

    int i, j, l;
    int lineSizeBytes = ((m_HWParams->RGBAvailable)?3:1)*m_ConvertedImage.height ()*(m_HWParams->ColorDepth)/8;
    int pixPerByte = 8/m_HWParams->ColorDepth;

    int imageSizeBytes = ((m_HWParams->RGBAvailable)?3:1)*m_ConvertedImage.width ()*m_ConvertedImage.height ()*(m_HWParams->ColorDepth)/8;
    if (imageSizeBytes > m_HWParams->FlashBlockSizeBytes*m_HWParams->NumOfBlocksForFrame)
    {
        imageSizeBytes = m_HWParams->FlashBlockSizeBytes*m_HWParams->NumOfBlocksForFrame;
        // Problem here!!
    }
    m_HWDataSize = imageSizeBytes;

    for (i = 0; i < m_ConvertedImage.width (); i++)
    {
        unsigned char *column = &(m_HWData[lineSizeBytes*i]);
        int k = 0;

        for (j = 0, k = 0, l = 3; j < m_ConvertedImage.height ()/2; j++, k=(k+1)%pixPerByte)
        {
            int r1 = m_ConvertedImage.height ()/2-j-1;
            int r2 = m_ConvertedImage.height ()/2+j;

            QRgb col1 = m_ConvertedImage.pixel(i,(r1/4+1)*4-l-1);
            QRgb col2 = m_ConvertedImage.pixel(i,(r2/4)*4+l);

            unsigned char R1 = qRed(col1);
            unsigned char G1 = qGreen(col1);
            unsigned char B1 = qBlue(col1);
            unsigned char R2 = qRed(col2);
            unsigned char G2 = qGreen(col2);
            unsigned char B2 = qBlue(col2);

            column  [   j/pixPerByte                                 ] |= B2<<(m_HWParams->ColorDepth*(pixPerByte-k-1));
            column  [   j/pixPerByte+lineSizeBytes/2                 ] |= B1<<(m_HWParams->ColorDepth*(pixPerByte-k-1));
            column  [   j/pixPerByte+lineSizeBytes/6                 ] |= G2<<(m_HWParams->ColorDepth*(pixPerByte-k-1));
            column  [   j/pixPerByte+lineSizeBytes/6+lineSizeBytes/2 ] |= G1<<(m_HWParams->ColorDepth*(pixPerByte-k-1));
            column  [   j/pixPerByte+lineSizeBytes/3                 ] |= R2<<(m_HWParams->ColorDepth*(pixPerByte-k-1));
            column  [   j/pixPerByte+lineSizeBytes/3+lineSizeBytes/2 ] |= R1<<(m_HWParams->ColorDepth*(pixPerByte-k-1));

            l --;
            if (l<0) l = 3;
        }
    }
}

//_________________________________________________________________________
void QImageProcessScene::convertToAniBikeFrame(void)
{
    memset(m_HWData, 0, m_HWDataSize);

    if (m_ConvertedImage.isNull ())
    {
        qDebug ("The converted image m_ConvertedImage is not valid.\n");
        return ;
    }

    int i, j, iInter;
    int pol;
    int numStripes = 2;

    int lineSizeBytes = ((m_HWParams->RGBAvailable)?3:1)*m_ConvertedImage.height()*(m_HWParams->ColorDepth)/8;
    int pixPerByte = 8/m_HWParams->ColorDepth;

    int imageSizeBytes = ((m_HWParams->RGBAvailable)?3:1)*m_ConvertedImage.width ()*m_ConvertedImage.height ()*(m_HWParams->ColorDepth)/8;
    if (imageSizeBytes > m_HWParams->FlashBlockSizeBytes*m_HWParams->NumOfBlocksForFrame)
    {
        imageSizeBytes = m_HWParams->FlashBlockSizeBytes*m_HWParams->NumOfBlocksForFrame;
        qDebug ("The must be a mistake - flashBlock*numBlockPerFrame < imageSize.\n");
        // Problem here!!
    }

    // store the size in bytes of the image
    m_HWDataSize = imageSizeBytes;

    // run over all angles
    for (iInter = 0; iInter < m_ConvertedImage.width ()/numStripes; iInter++)
    {
        // Here we have the ability to control the direction and the starting point
        // of the angles. In m_ConvertedImage, when we point on the iInter=0, we are talking
        // about angle "0" (X positive). when we grow this number we go CW.
        // If we want to add a phase to this stuff we need to use something like
        //
        //      i = ( iInter + iPhase ) % m_ConvertedImage.width();
        //
        i = iInter;
        int k = 0;

        for (pol = 0; pol < numStripes; pol ++)
        {
            // isolate the appropriate column
            unsigned char *column = &(m_HWData[lineSizeBytes*(numStripes*i+pol)]);
            int xIm = m_ConvertedImage.width()/numStripes*pol+i;

            for (j=0,k = 0; j < m_ConvertedImage.height (); j++, k=(k+1)%pixPerByte)
            {
                int yIm = j;
                QRgb col = m_ConvertedImage.pixel(xIm,yIm);

                unsigned char R = qRed(col);
                unsigned char G = qGreen(col);
                unsigned char B = qBlue(col);

                column  [ j/pixPerByte                   ] |= B<<(m_HWParams->ColorDepth*(pixPerByte-k-1));
                column  [ j/pixPerByte+  lineSizeBytes/3 ] |= G<<(m_HWParams->ColorDepth*(pixPerByte-k-1));
                column  [ j/pixPerByte+2*lineSizeBytes/3 ] |= R<<(m_HWParams->ColorDepth*(pixPerByte-k-1));
            }
        }
    }
}

//_________________________________________________________________________
int QImageProcessScene::convertFromMoussaviFrame ( void )
{
    if (m_HWData == NULL || m_HWDataSize == 0)
    {
        // Problem here!!
        return -1;
    }

    int i, j, l;
    int lineSizeBytes = ((m_HWParams->RGBAvailable)?3:1)*m_ConvertedImage.height ()*(m_HWParams->ColorDepth)/8;
    int pixPerByte = 8/m_HWParams->ColorDepth;
    int imageWidth = m_HWDataSize/lineSizeBytes;
    int imageHeight = m_HWParams->NumberOfLEDs;
    int numOfLevelsMask = (int)(pow(2.0, m_HWParams->ColorDepth))-1;        // 4 => 1111 (15); 2 => 11 (3) ...
    int numColLevels = (int)(pow(2.0, m_HWParams->ColorDepth));
    double stepSize = 256.0/numColLevels;

    m_ConvertedImage = QImage(imageWidth, m_HWParams->NumberOfLEDs, QImage::Format_ARGB32);

    for (i = 0; i < imageWidth; i++)
    {
        unsigned char *column = &(m_HWData[lineSizeBytes*i]);
        int k = 0;

        for (j = 0, k = 0, l = 3; j < m_ConvertedImage.height ()/2; j++, k=(k+1)%pixPerByte)
        {
            int r1 = imageHeight/2-j-1;
            int r2 = imageHeight/2+j;

            unsigned char R1;
            unsigned char G1;
            unsigned char B1;
            unsigned char R2;
            unsigned char G2;
            unsigned char B2;

            B2 = (column  [   j/pixPerByte                                 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            B1 = (column  [   j/pixPerByte+lineSizeBytes/2                 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            G2 = (column  [   j/pixPerByte+lineSizeBytes/6                 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            G1 = (column  [   j/pixPerByte+lineSizeBytes/6+lineSizeBytes/2 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            R2 = (column  [   j/pixPerByte+lineSizeBytes/3                 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            R1 = (column  [   j/pixPerByte+lineSizeBytes/3+lineSizeBytes/2 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;

            QRgb col1 = qRgb(R1, G1, B1);
            QRgb col2 = qRgb(R2, G2, B2);

            m_ConvertedImage.setPixel(i,(r1/4+1)*4-l-1, col1);
            m_ConvertedImage.setPixel(i,(r2/4)*4+l, col2);

            l --;
            if (l<0) l = 3;
        }
    }

    m_ViewedImage = m_ConvertedImage.scaledToHeight(150);
    m_ViewedImage.convertToFormat(QImage::Format_ARGB32);

    for (int i=0; i<m_ViewedImage.width(); i++)
    {
        for (int j=0; j<m_ViewedImage.height(); j++)
        {
            QRgb col = m_ViewedImage.pixel(i,j);
            int R = qRed(col)*stepSize+stepSize/2.0;
            int G = qGreen(col)*stepSize+stepSize/2.0;
            int B = qBlue(col)*stepSize+stepSize/2.0;

            col = qRgb(R, G, B);

            m_ViewedImage.setPixel(i,j,col);
        }
    }

    this->clear();

    return 0;
}

//_________________________________________________________________________
int QImageProcessScene::convertFromAniBikeFrame ( void )
{
    if (m_HWData == NULL || m_HWDataSize == 0)
    {
        // Problem here!!
        return -1;
    }

    int i, j, l;

    int lineSizeBytes = ((m_HWParams->RGBAvailable)?3:1)*m_ConvertedImage.height()*(m_HWParams->ColorDepth)/8;
    int pixPerByte = 8/m_HWParams->ColorDepth;
    int imageWidth = m_HWDataSize/lineSizeBytes;        // the converted hardware polar image
    int imageHeight = m_HWParams->NumberOfLEDs;

    int numOfLevelsMask = (int)(pow(2.0, m_HWParams->ColorDepth))-1;        // 4 => 1111 (15); 2 => 11 (3) ...
    int numColLevels = (int)(pow(2.0, m_HWParams->ColorDepth));
    double stepSize = 256.0/numColLevels;

    QImage polarImage_int(imageWidth, m_HWParams->NumberOfLEDs, QImage::Format_ARGB32);

    for (i = 0; i < imageWidth; i++)
    {
        unsigned char *column = &(m_HWData[lineSizeBytes*i]);
        int k = 0;

        for (j = 0, k = 0, l = 3; j < polarImage_int.height ()/2; j++, k=(k+1)%pixPerByte)
        {
            int r1 = imageHeight/2-j-1;
            int r2 = imageHeight/2+j;

            unsigned char R1;
            unsigned char G1;
            unsigned char B1;
            unsigned char R2;
            unsigned char G2;
            unsigned char B2;

            B2 = (column  [   j/pixPerByte                                 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            B1 = (column  [   j/pixPerByte+lineSizeBytes/2                 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            G2 = (column  [   j/pixPerByte+lineSizeBytes/6                 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            G1 = (column  [   j/pixPerByte+lineSizeBytes/6+lineSizeBytes/2 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            R2 = (column  [   j/pixPerByte+lineSizeBytes/3                 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;
            R1 = (column  [   j/pixPerByte+lineSizeBytes/3+lineSizeBytes/2 ]>>(m_HWParams->ColorDepth*(pixPerByte-k-1)))&numOfLevelsMask;

            R1 = R1*stepSize+stepSize/2.0;
            R2 = R2*stepSize+stepSize/2.0;
            G1 = G1*stepSize+stepSize/2.0;
            G2 = G2*stepSize+stepSize/2.0;
            B1 = B1*stepSize+stepSize/2.0;
            B2 = B2*stepSize+stepSize/2.0;

            QRgb col1 = qRgb(R1, G1, B1);
            QRgb col2 = qRgb(R2, G2, B2);

            polarImage_int.setPixel(i,(r1/4+1)*4-l-1, col1);
            polarImage_int.setPixel(i,(r2/4)*4+l, col2);

            l --;
            if (l<0) l = 3;
        }
    }

    polarImage_int.save("c://anibike_rec.bmp");

/*    QImage viewedImage_int( ANIBIKE_WHEEL_RADIUS*2, ANIBIKE_WHEEL_RADIUS*2, QImage::Format_ARGB32 );
    double radOut = ANIBIKE_WHEEL_RADIUS;
    double radIn = ANIBIKE_WHEEL_RADIUS*ANIBIKE_INNER_RAD_RATIO;
    double dRad = (radOut - radIn)/m_HWParams->NumberOfLEDs;
    double dPhi = 360.0 / (double)(ANIBIKE_NUMOFRADS);      //255
    double phiStart = 0.0;      // fisrt map 0->360
    double curRad, curPhi;
    int radY, phiX;

    for (i=0, curPhi=phiStart; i<polarImage_int.width(); i++, curPhi+=dPhi)        // over the phi axis
    {
        for (j=0, curRad=radIn; j<polarImage_int.height(); j++, curRad+=1.0)   // over the r axis
        {
            QRgb pixCol = polarImage_int.pixel(i,j);
            double dCurX = curRad*cos(curPhi*ANIBIKE_PI/180.0);
            double dCurY = curRad*sin(curPhi*ANIBIKE_PI/180.0);

            //int curX = (dCurX)
        }
    }

    this->clear();*/

    return 0;
}

//_________________________________________________________________________
int QImageProcessScene::convertFromHardwareFrame (unsigned char* data, int size)
{
    if (data == NULL || size <= 0)
        return -1;

    m_HWDataSize = size;
    memcpy (m_HWData, data, m_HWDataSize);

    if (m_SceneType == SCENE_MOUSSAVI)
        convertFromMoussaviFrame();
    else if (m_SceneType == SCENE_ANIBIKE)
        convertFromAniBikeFrame();

    return 0;
}

//_________________________________________________________________________
int QImageProcessScene::GetFrameWidth(void)
{
    if (m_ConvertedImage.isNull ())
        return -1;

    return m_ConvertedImage.width ();
}

//_________________________________________________________________________
void QImageProcessScene::GetHWData(int *length, unsigned char **data)
{
    *data = m_HWData;
    *length = m_HWDataSize;
}

//_________________________________________________________________________
void QImageProcessScene::SetHWData(int length, unsigned char *data)
{
    convertFromHardwareFrame (data, length);

    this->invalidate ();
}

//_________________________________________________________________________
void QImageProcessScene::UpdateMoussavi()
{
    double numColLevels = pow(2.0, m_HWParams->ColorDepth);
    double colorSteps = 256.0 / numColLevels;

    // Update the shown pictures size
    m_ConvertedImage = m_LoadedImage.scaledToHeight(m_HWParams->NumberOfLEDs);

    // TBD Convert to depth
    convertColorDepth(m_ConvertedImage);

    m_ViewedImage = m_ConvertedImage.scaledToHeight(150);
    //m_ViewedImage.convertToFormat(QImage::Format_ARGB32);

    for (int i=0; i<m_ViewedImage.width(); i++)
    {
        for (int j=0; j<m_ViewedImage.height(); j++)
        {
            QRgb col = m_ViewedImage.pixel(i,j);
            int R = qRed(col)*colorSteps+colorSteps/2.0;
            int G = qGreen(col)*colorSteps+colorSteps/2.0;
            int B = qBlue(col)*colorSteps+colorSteps/2.0;

            col = qRgba(R, G, B, 128);

            m_ViewedImage.setPixel(i,j,col);
        }
    }

    // Convert to wanted hardware format
    convertToHardwareFrame();

    this->clear();
}

//_________________________________________________________________________
void QImageProcessScene::UpdateAniBike()
{
    QImage tempImage;

    int drawRadius = ANIBIKE_WHEEL_RADIUS;
    int width = m_LoadedImage.width ();
    int height = m_LoadedImage.height ();

    if (width>height)
        tempImage = m_LoadedImage.scaledToHeight(drawRadius*2);
    else
        tempImage = m_LoadedImage.scaledToWidth (drawRadius*2);

    m_ViewedImage = QImage( drawRadius*2, drawRadius*2, QImage::Format_ARGB32 );
    m_ViewedImageRear = QImage( drawRadius*2, drawRadius*2, QImage::Format_ARGB32 );

    m_ConvertedImage = m_LoadedImage;
    convertPolarPicture (m_ConvertedImage, ANIBIKE_INNER_RAD_RATIO);
    convertColorDepth (m_ConvertedImage);
    m_ConvertedImage.save("c://anibike_converted.bmp");

    int centerX = tempImage.width ()/2;
    int centerY = tempImage.height ()/2;

    // modify the image before resizing
    for (int i=centerX-drawRadius; i<centerX+drawRadius; i++)
    {
        for (int j=centerY-drawRadius; j<centerY+drawRadius; j++)
        {
            QRgb col = tempImage.pixel(i,j);
            QRgb resColFront, resColRear;
            double xPlace = i-centerX;
            double yPlace = j-centerY;
            double curRad = sqrt(xPlace*xPlace+yPlace*yPlace);

            double curArg;

            if (xPlace!=0.0)
                curArg = atan(yPlace/xPlace);
            else
            {
                curArg = ANIBIKE_PI*(yPlace>=0?1.0:-1.0);
            }

            if ( curRad>=drawRadius || curRad<=(drawRadius/9.0) )
            {
                resColFront = qRgba(0,0,0,0);
                resColRear = qRgba(0,0,0,0);
            }
            else
            {
                double alpha = sin((curRad/drawRadius)*ANIBIKE_PI*m_HWParams->NumberOfLEDs*9.0/8.0);
                alpha *= alpha;

                resColFront = qRgba (qRed(col), qGreen(col), qBlue(col), alpha*255);
                resColRear = qRgba (qRed(col), qGreen(col), qBlue(col), alpha*255);
            }

            m_ViewedImage.setPixel (i-(centerX-drawRadius),j-(centerY-drawRadius),resColFront);
            m_ViewedImageRear.setPixel (i-(centerX-drawRadius),j-(centerY-drawRadius),resColRear);
        }

    }


    // Convert to wanted hardware format
    convertToHardwareFrame();

    this->clear();

}

//_________________________________________________________________________
void QImageProcessScene::UpdateUnknown()
{

}

//_________________________________________________________________________
void QImageProcessScene::Update()
{
    if (m_SceneType == SCENE_MOUSSAVI)
        UpdateMoussavi();
    else if (m_SceneType == SCENE_ANIBIKE)
        UpdateAniBike();
    else
        UpdateUnknown();

    this->invalidate();
}

//_________________________________________________________________________
void QImageProcessScene::SetImagePath(QString path)
{
    if (path.isNull() || path.isEmpty())
        return;

    m_LoadedImage.load(path);

    Update();
}

//_________________________________________________________________________
void QImageProcessScene::SetFrameHeight(int fheight)
{
    m_FrameHeight=fheight;
    Update();
}

//_________________________________________________________________________
void QImageProcessScene::SetFrameWidth(int fwidth)
{
    m_FrameWidth=fwidth;
    Update();
}

//_________________________________________________________________________
void QImageProcessScene::drawBackground(QPainter *painter, const QRectF &exposed)
{
    if (m_BackgroundImage.width()<200)
    {
        painter->fillRect(exposed,Qt::darkGray);
    }
    else
    {
        painter->setWindow(m_FrameWidth/2-1,m_FrameHeight/2-2,
                           m_FrameWidth,m_FrameHeight);
        painter->drawPixmap(QPoint(0,0),
                            QPixmap::fromImage(m_BackgroundImage));
    }

    QGraphicsScene::drawBackground(painter, exposed);
}

//_________________________________________________________________________
void QImageProcessScene::drawForeground(QPainter *painter, const QRectF &rect)
{
    if (m_SceneType == SCENE_MOUSSAVI)
    {
        drawMoussavi(painter, rect);
    }
    else if (m_SceneType == SCENE_ANIBIKE)
    {
        drawAniBike(painter, rect);
    }
    else
    {
        // Do Nothing
    }

    QGraphicsScene::drawForeground(painter, rect);
}

//_________________________________________________________________________
void QImageProcessScene::drawMoussavi(QPainter *painter, const QRectF &rect)
{
    painter->setOpacity(0.6);
    painter->drawPixmap(QPoint(-m_ViewedImage.width()/2-3,-m_ViewedImage.height()/2-36),
                        QPixmap::fromImage(m_ViewedImage));
}

//_________________________________________________________________________
void QImageProcessScene::drawAniBike(QPainter *painter, const QRectF &rect)
{
    painter->setOpacity(0.9);
    painter->drawPixmap(QPoint(-m_ViewedImage.width()/2+14,-m_ViewedImage.height()/2+12),
                        QPixmap::fromImage(m_ViewedImage));

    painter->setOpacity(1.0);
    painter->drawPixmap(-284,
                        -214,
                        m_ForegroundImage.width (),
                        m_ForegroundImage.height (),
                        QPixmap::fromImage(m_ForegroundImage));
}

//_________________________________________________________________________
void QImageProcessScene::ClearScreen(void)
{
    if (!m_ViewedImage.isNull ()) m_ViewedImage = QImage();
    this->invalidate ();
}

//_________________________________________________________________________
QImage& QImageProcessScene::getLoadedImage (void)
{
    return m_LoadedImage;
}

//_________________________________________________________________________
void QImageProcessScene::setLoadedImage (QImage& image)
{
    m_LoadedImage = image;
    Update();
}

